﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace DigestChecker.Cryptography
{
    internal sealed class Crc32CryptoServiceProvider : Crc32
    {
        /// <summary>
        /// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
        /// </summary>
        public override void Initialize()
        {
        }

        /// <summary>
        /// When overridden in a derived class, routes data written to the object into the hash algorithm for computing the hash.
        /// </summary>
        /// <param name="array">The input to compute the hash code for. </param>
        /// <param name="ibStart">The offset into the byte array from which to begin using data. </param>
        /// <param name="cbSize">The number of bytes in the byte array to use as data. </param>
        protected override void HashCore(byte[] array, int ibStart, int cbSize)
        {
            //byte[] bytes = {};
            //Array.Copy(array, ibStart, bytes, 0, cbSize);
            if (ibStart == 0 && cbSize == array.Length)
            {
                HashValue = ComputeChecksumBytes(array);
            }
            else
            {

                var bytes = new List<byte>();
                var segment = new ArraySegment<byte>(array, ibStart, cbSize);
                for (int i = segment.Offset; i < (segment.Offset + segment.Count); i++)
                {
                    bytes.Add(segment.Array[i]);
                } //var b = GetArray(segment);
                //bytes.AddRange(b);

                HashValue = ComputeChecksumBytes(bytes.ToArray());
            }
        }

        /// <summary>
        /// When overridden in a derived class, finalizes the hash computation after the last data is processed by the cryptographic stream object.
        /// </summary>
        /// <returns>
        /// The computed hash code.
        /// </returns>
        protected override byte[] HashFinal()
        {
            return HashValue;
        }

        private static IEnumerable<byte> GetArray(ArraySegment<byte> segment)
        {
            for (int i = segment.Offset; i < (segment.Offset + segment.Count); i++)
            {
                yield return segment.Array[i];
            }
        }
    }
}
